package com.sdvdxl.oauth;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import com.sdvdxl.exceptios.NetworkException;
import com.sdvdxl.exceptios.UnGrantException;

/**
 * 授权管理
 * @author sdvdxl (sdvdxl@163.com)
 * 
 */
public class GrantManager {
	/** 用client_id换取的access_token值  */
	public static String ACCESS_TOKEN;
	private String scope;
	private String url;
	private String[] scopes;
	private String clientId;
	private String redirectURL;
	
	/** 用户基本权限，可以获取用户的基本信息  */
	public static final String BASIC = "basic";
	
	/**
	 * 往用户的百度首页上发送消息提醒
	 * 相关API任何应用都能使用
	 * 但要想将消息提醒在百度首页显示
	 * 需要第三方在注册应用时额外填写相关信息
	 */
	public static final String SUPER_MSG  = "super_msg";
	
	/** 获取用户在个人云存储中存放的数据  */
	public static final String NETDISK = "netdisk";
	
	/**
	 * 默认授权，即 basic权限
	 * @param clientId API Key
	 */
	public GrantManager(String clientId, String redirectURL) {
		this.clientId = clientId;
		this.redirectURL = redirectURL;
		scopes = new String[1];
		scopes[0] = "basic";
		setScopes(scopes);
	}
	
	/**
	 * 用户自主授权
	 * 权限必须是GrantManager权限列表中的
	 * @param clientId API Key
	 * @param scope
	 */
	public GrantManager(String clientId, String redirectURL, String scope) {
		this.clientId = clientId;
		this.redirectURL = redirectURL;
		scopes = new String[1];
		scopes[0] = scope;
		setScopes(scopes);
	}
	
	/**
	 * 设置权限范围 可以同时设置多个权限
	 * @param clientId API Key
	 * @param scopes 权限范围
	 */
	public GrantManager(String clientId, String redirectURL, String[] scopes) {
		this.clientId = clientId;
		this.scopes = scopes;
		this.redirectURL = redirectURL;
		setScopes(scopes);
	}
	
	/**
	 * 取得应用的权限
	 * @return String[]
	 */
	public String[] getScopes() {
		return scopes;
	}

	/**
	 * 设置权限范围
	 * @param scopes 权限范围
	 */
	public void setScopes(String[] scopes) {
		scope = new String();
		for (int i = 0; i < scopes.length; i++) {
			scope += scopes[i] + ",";
		}

		scope = scope.substring(0, scope.length() - 1);
		
		//设置授权url
		setGrantUrl();
	}
	
	/**
	 * 取得用client_id换取的access_token值
	 * @return access_token
	 */
	public String getAccessToken() {
		return ACCESS_TOKEN;
	}

	public void setAccessToken(String accessToken) {
		ACCESS_TOKEN = accessToken;
	}
	
	/**
	 * 授权URL
	 * @return 授权地址
	 */
	public String getGrantURL() {
		return url;
	}
	
	private void setGrantUrl() {
		url = "https://openapi.baidu.com/oauth/2.0/authorize?" 
				+ "response_type=token&client_id=" + clientId 
				+ "&redirect_uri=" + redirectURL + "&scope=" + scope;
	}
	
	/**
	 * 撤销当前登录用户授予第三方应用的权限
	 * @return 撤销成功true 否则false
	 * @throws NetworkException 
	 * @throws UnGrantException 
	 */
	public static boolean removeGrant() throws NetworkException, UnGrantException {
		if (ACCESS_TOKEN==null) {
			throw new UnGrantException("未授权");
		}
		
		String xmlURL = "https://openapi.baidu.com/rest/2.0/passport/auth/revokeAuthorization?" +
				"access_token=" + GrantManager.ACCESS_TOKEN
				+ "&format=xml";
		
		return interimRemoveGrant(xmlURL);
	}
	
	/**
	 * 撤销指定用户授予第三方应用的权限
	 * @param uid 指定用户的数字id
	 * @return 撤销成功true 否则false
	 * @throws NetworkException 
	 * @throws UnGrantException 
	 */
	public static boolean removeGrant(String uid) throws NetworkException, UnGrantException {
		if (ACCESS_TOKEN==null) {
			throw new UnGrantException("未授权");
		}
		
		String xmlURL = "https://openapi.baidu.com/rest/2.0/passport/auth/revokeAuthorization?" +
				"access_token=" + GrantManager.ACCESS_TOKEN
				+ "&format=xml&uid=" + uid;
		
		return interimRemoveGrant(xmlURL);
	}
	
	private static boolean interimRemoveGrant(String xmlURL) throws NetworkException, UnGrantException {
		Document doc = null;
		String basic = "//passport_auth_revokeAuthorization_response/";
		
		try {
			URL url = new URL(xmlURL);
			URLConnection uc = url.openConnection();
			doc = new SAXReader().read(uc.getInputStream());
		} catch (DocumentException | IOException e) {
			throw new NetworkException("网络异常" + e);
		}

		Node nodeInf = doc.selectSingleNode(basic + "result");
		if (nodeInf==null) {
			throw new UnGrantException("未授权");
		}
		
		String inf = nodeInf.getText().trim();
		if ("1".equals(inf)) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * 当前登陆用户是否已经授权
	 * @return 已授权 true 未授权 false
	 * @throws UnGrantException 
	 */
	public static boolean isAppUser() throws UnGrantException {
		if (ACCESS_TOKEN==null) {
			throw new UnGrantException("未授权");
		}
		
		return false;
	}
	
	/**
	 * 指定用户是否已经授权
	 * @param uid 指定用户的数字id
	 * @return 已授权 true 未授权 false
	 * @throws UnGrantException 
	 */
	public static boolean isAppUser(String uid) throws UnGrantException {
		if (ACCESS_TOKEN==null) {
			throw new UnGrantException("未授权");
		}
		
		return false;
	}
	
	/**
	 * 
	 * @param extPerm 权限 必须是GrantManager中的常量
	 * @return 有该项权限 true 否则 false
	 * @throws NetworkException
	 * @throws UnGrantException
	 */
	public static boolean hasAppPermission(String extPerm) throws NetworkException, UnGrantException {
		String xmlURL = "https://openapi.baidu.com/rest/2.0/passport/users/hasAppPermission?"
				 + "access_token=" + GrantManager.ACCESS_TOKEN 
				 + "&format=xml"
				 + "&ext_perm=" + extPerm;
		
		Document doc = null;
		String basic = "//passport_users_hasAppPermission_response/";
		
		try {
			URL url = new URL(xmlURL);
			URLConnection uc = url.openConnection();
			doc = new SAXReader().read(uc.getInputStream());
		} catch (DocumentException | IOException e) {
			throw new NetworkException("网络异常" + e);
		}

		Node nodeInf = doc.selectSingleNode(basic + "result");
		if (nodeInf==null) {
			throw new UnGrantException("未授权");
		}
		
		String inf = nodeInf.getText().trim();
		if ("1".equals(inf)) {
			return true;
		}
		
		return false;
	}
}
